﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using RobotControl.Tools.UserControls;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace LocalizationTest.Tools
{
  class DebugDrawingTool
  {
    public class State
    {
      private bool disabeled = false;
      private List<string> drawingPanelIDs = new List<string>();
      private List<object[]> drawings = new List<object[]>();
      private int bmpExportCounter = 0;
      private int sessionCounter = 0;

      public bool Disabeled
      {
        get { return disabeled; }
        set { disabeled = value; }
      }
      public List<string> DrawingPanelIDs
      {
        get { return drawingPanelIDs; }
        set { drawingPanelIDs = value; }
      }
      public List<object[]> Drawings
      {
        get { return drawings; }
        set { drawings = value; }
      }
      public int BmpExportCounter
      {
        get { return bmpExportCounter; }
        set { bmpExportCounter = value; }
      }
      public int SessionCounter
      {
        get { return sessionCounter; }
        set { sessionCounter = value; }
      }
    }
    public static State state = new State();

    private static NameSpaceTreeView2 nameSpaceTreeView;
    private static DrawingPanelContainer drawingPanelContainer;

    public static void SetNameSpaceTreeView(NameSpaceTreeView2 nst)
    {
      nameSpaceTreeView = nst;
    }
    public static void SetDrawingPanelContainer(DrawingPanelContainer dpc)
    {
      drawingPanelContainer = dpc;
    }

    public static void ResetDrawings()
    {
      state.Drawings.Clear();
    }
    public static void ResetDrawingIDs()
    {
      nameSpaceTreeView.NodeIDs.Clear();
      state.Drawings.Clear();
      nameSpaceTreeView.Clear();
      nameSpaceTreeView.UpdateTree();
    }
    public static void DisableAll()
    {
      Dictionary<string, LocalizationTest.Tools.NameSpaceTreeView2.NodeProperties> copiedDrawingIDs = new Dictionary<string, LocalizationTest.Tools.NameSpaceTreeView2.NodeProperties>();
      foreach (string key in nameSpaceTreeView.NodeIDs.Keys)
      {
        copiedDrawingIDs[key] = new NameSpaceTreeView2.NodeProperties(false, nameSpaceTreeView.NodeIDs[key].isKnown);
      }
      nameSpaceTreeView.NodeIDs = copiedDrawingIDs;
    }

    public static void CreateMetafiles(string fileNameBase)
    {
      foreach (string drawingID in nameSpaceTreeView.NodeIDs.Keys)
      {
        string emfFileName = fileNameBase + drawingID.Replace(':', '_') + ".emf";

        Metafile mf;
        Graphics graphics;
        DrawingTools.CreateMetaFileGraphics(emfFileName, out mf, out graphics);

        bool somethingWasDrawn = false;
        /*
        foreach (Drawing drawing in drawings)
        {
          if (drawingID == drawing.drawingID && state.DrawingIDs[drawingID] == true)
          {
            somethingWasDrawn = true;
            DrawSingleDrawing(graphics, drawing);
          }
        }
         */ 
        DrawingTools.FinishMetaFileGraphics(mf, graphics);
        if (!somethingWasDrawn)
          System.IO.File.Delete(emfFileName);
      }
    }

    /** dot, drawingID, x, y, r, g, b, size */
    public static void CreateDrawing(string id, object[] parameters)
    {
      if(state.Disabeled) return;
      state.Drawings.Add(parameters);
      AddDrawingID((parameters[1] as string).Trim());
    }
    public static void AddDrawingID(string drawingID)
    {
      if (!nameSpaceTreeView.NodeIDs.ContainsKey(drawingID))
      {
        string[] part = drawingID.Split(':');
        if (!state.DrawingPanelIDs.Contains(part[0]))
        {
          state.DrawingPanelIDs.Add(part[0]);
          System.Windows.Forms.Panel newPanel = drawingPanelContainer.AddPanel(part[0]);
          newPanel.Paint += new System.Windows.Forms.PaintEventHandler(newPanel_Paint);
        }
      }
      nameSpaceTreeView.AddOrConfirmValue(drawingID);
    }
    static void newPanel_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
//      DebugTextTool.Output("DebugDrawingTool:newPanel_Paint");

      string panelID = "";
      Panel senderAsPanel = sender as Panel;
      foreach (string key in drawingPanelContainer.panelIDs.Keys)
      {
        if (drawingPanelContainer.panelIDs[key].Panel == sender)
          panelID = key;
      }

      if (drawingPanelContainer.panelIDs[panelID].LinkLabelHide.Text != "hide") return;

      float centerX = senderAsPanel.Width / 2;
      float centerY = senderAsPanel.Height / 2;
      Graphics graphics = e.Graphics;
      if (drawingPanelContainer.panelIDs[panelID].SaveBmp)
      {
        Brush whiteBrush = new SolidBrush(Color.White);
        graphics.FillRectangle(whiteBrush, -400 + centerX, -300 + centerY, 800, 600);
      }
      if (panelID == "time_line")
      {
        centerX = 30;
        centerY = senderAsPanel.Height - 30;
      }
      PaintPanelToGraphics(panelID, centerX, centerY, graphics);
    }
    private static void PaintPanelToGraphics(string panelID, float centerX, float centerY, Graphics graphics)
    {
      double zoom = drawingPanelContainer.panelIDs[panelID].Zoom;
      float angle = (float)drawingPanelContainer.panelIDs[panelID].Angle;
      graphics.TranslateTransform(centerX, centerY);
      graphics.ScaleTransform((float)zoom, -(float)zoom);
      graphics.RotateTransform(angle);

      foreach (object[] parameters in state.Drawings)
      {
        string drawingID = (parameters[1] as string).Trim();
        if (drawingID.StartsWith(panelID))
          DrawSingleDrawing(graphics, parameters);
      }
    }
    public static void SaveBitmaps()
    {
      state.BmpExportCounter++;
      foreach (string panelID in state.DrawingPanelIDs)
      {
        if (drawingPanelContainer.panelIDs[panelID].SaveBmp)
        {
          Bitmap bmp = new Bitmap(800, 600);
          Graphics graphics = Graphics.FromImage(bmp);

          Brush whiteBrush = new SolidBrush(Color.White);
          graphics.FillRectangle(whiteBrush, 0, 0, 800, 600);

          PaintPanelToGraphics(panelID, 400, 300, graphics);

          string fileName =
            DrawingTools.GetVideoOutputPath() +
            DateTime.Now.Date.Year + "-" +
            DateTime.Now.Date.Month.ToString("00") + "-" +
            DateTime.Now.Date.Day +
            "_" +
            panelID +
            "_" +
            state.SessionCounter.ToString("00") + "_" +
            state.BmpExportCounter.ToString("000") + "_" + 
            ".bmp";
            bmp.Save(fileName);
        }
      }
    }

    public static void SaveMetafiles()
    {
      state.BmpExportCounter++;
      foreach (string panelID in state.DrawingPanelIDs)
      {
        if (drawingPanelContainer.panelIDs[panelID].SaveEMF)
        {
          string fileName =
            DrawingTools.GetVideoOutputPath() +
            DateTime.Now.Date.Year + "-" +
            DateTime.Now.Date.Month.ToString("00") + "-" +
            DateTime.Now.Date.Day +
            "_" +
            panelID +
            "_" +
            state.SessionCounter.ToString("00") + "_" +
            state.BmpExportCounter.ToString("000") + "_" +
            ".emf";

          Metafile mf;
          Graphics graphics;
          DrawingTools.CreateMetaFileGraphics(fileName, out mf, out graphics);

//          bool somethingWasDrawn = false;

          Brush whiteBrush = new SolidBrush(Color.White);
          graphics.FillRectangle(whiteBrush, 0, 0, 800, 600);

          PaintPanelToGraphics(panelID, 400, 300, graphics);
          DrawingTools.FinishMetaFileGraphics(mf, graphics);
//          if (!somethingWasDrawn)
//            System.IO.File.Delete(fileName);
        }
      }
    }

    public static void Draw(Graphics graphics)
    {
//      DebugTextTool.Output("DebugDrawingTool:Draw");
      foreach (object[] parameters in state.Drawings)
      {
        DrawSingleDrawing(graphics, parameters);
      }
    }

    [ProfileManager.StateSaving]
    public static string GetState()
    {
      string stateString = "";
      foreach (string key in nameSpaceTreeView.NodeIDs.Keys)
      {
        if (nameSpaceTreeView.NodeIDs[key].isChecked) stateString += key + ";";
      }
      return stateString;
    }
    public static void SetState(string stateString)
    {
      DisableAll();
      string[] parts = stateString.Split(';');
      foreach (string part in parts)
      {
        nameSpaceTreeView.SetCheck(part, true);
      }
      nameSpaceTreeView.UpdateTree();
      nameSpaceTreeView.TreeView.ExpandAll();
    }

    #region add new drawingtype here
    private static void DrawSingleDrawing(Graphics graphics, object[] drawingDescription)
    {
      switch (drawingDescription[0] as string)
      {
        case "dot": DrawDot(drawingDescription, graphics); break;
        case "circle": DrawCircle(drawingDescription, graphics); break;
        case "filledCircle": DrawFilledCircle(drawingDescription, graphics); break;
        case "rectangle": DrawRectangle(drawingDescription, graphics); break;
        case "line": DrawLine(drawingDescription, graphics); break;
        case "arrow": DrawArrow(drawingDescription, graphics); break;
        case "text": DrawText(drawingDescription, graphics); break;
        default:
          break;
      }
    }

    private static void DrawDot(object[] parameters, Graphics graphics)
    {
      string drawingID = (parameters[1] as string).Trim();
      if (nameSpaceTreeView.NodeIDs[drawingID].isChecked)
      {
        Vector2 center = (Vector2)parameters[2];
        float size = (float)parameters[3];
        Color color = (Color)parameters[4];

        Pen pen = new Pen(color, (float)(Globals.rasterWidth / 10.0));
        SolidBrush brush = new SolidBrush(color);
        graphics.FillRectangle(brush,
          (float)(center.x - size / 2.0),
          (float)(center.y - size / 2.0),
          size, size);
      }
    }
    private static void DrawCircle(object[] parameters, Graphics graphics)
    {
      string drawingID = (parameters[1] as string).Trim();
      if (nameSpaceTreeView.NodeIDs[drawingID].isChecked)
      {
        Vector2 center = (Vector2)parameters[2];
        double radius = (double)parameters[3];
        double lineWidth = (double)parameters[4];
        Color color = (Color)parameters[5];

        Pen pen = new Pen(color, (float)lineWidth);
        graphics.DrawEllipse(pen,
          (float)(center.x - radius),
          (float)(center.y - radius),
          (float)(radius * 2),
          (float)(radius * 2) );
      }
    }
    private static void DrawFilledCircle(object[] parameters, Graphics graphics)
    {
      string drawingID = (parameters[1] as string).Trim();
      if (nameSpaceTreeView.NodeIDs[drawingID].isChecked)
      {
        Vector2 center = (Vector2)parameters[2];
        double radius = (double)parameters[3];
        Color color = (Color)parameters[4];

        SolidBrush brush = new SolidBrush(color);
        graphics.FillEllipse(brush,
          (float)(center.x - radius),
          (float)(center.y - radius),
          (float)(radius * 2),
          (float)(radius * 2));
      }
    }
    private static void DrawRectangle(object[] parameters, Graphics graphics)
    {
      string drawingID = (parameters[1] as string).Trim();
      if (nameSpaceTreeView.NodeIDs[drawingID].isChecked)
      {
        Vector2 bottomLeftCorner = (Vector2)parameters[2];
        Vector2 topRightCorner = (Vector2)parameters[3];
        double lineWidth = (double)parameters[4];
        Color color = (Color)parameters[5];

        Pen pen = new Pen(color, (float)lineWidth);
        graphics.DrawRectangle(pen,
            (float)bottomLeftCorner.x, (float)bottomLeftCorner.y,
            (float)(topRightCorner.x - bottomLeftCorner.x),
            (float)(topRightCorner.y - bottomLeftCorner.y));
      }
    }
    private static void DrawArrow(object[] parameters, Graphics graphics)
    {
      string drawingID = (parameters[1] as string).Trim();
      if (nameSpaceTreeView.NodeIDs[drawingID].isChecked)
      {
        Vector2 start = (Vector2)parameters[2];
        Vector2 end = (Vector2)parameters[3];
        double lineWidth = (double)parameters[4];
        Color color = (Color)parameters[5];

        Pen pen = new Pen(color, (float)lineWidth);
        graphics.DrawLine(pen,
            (float)start.x, (float)start.y,
            (float)(end.x), (float)end.y);
        /*
        graphics.DrawEllipse(pen,
            (float)(end.x-1), (float)(end.y-1),
            (float)(2), (float)(2));*/

        double angle1 = (start - end).GetAngle() + Math.PI / 5.0;
        double angle2 = (start - end).GetAngle() - Math.PI / 5.0;
        double length = (end-start).Abs() * 0.5;
        
        PointF[] points = new PointF[3];

        points[0] = new PointF((float)(end.x + Math.Cos(angle1) * length), (float)(end.y + Math.Sin(angle1) * length));
        points[1] = new PointF((float)(end.x), (float)(end.y));
        points[2] = new PointF((float)(end.x + Math.Cos(angle2) * length), (float)(end.y + Math.Sin(angle2) * length));


        graphics.DrawLines(pen, points);
        /*
        graphics.DrawLine(pen,
            (float)(end.x), (float)(end.y),
            (float)(end.x + Math.Cos(angle1) * length), (float)(end.y + Math.Sin(angle1) * length));
        graphics.DrawLine(pen,
            (float)(end.x), (float)(end.y),
            (float)(end.x + Math.Cos(angle2) * length), (float)(end.y + Math.Sin(angle2) * length));
        */

      }
    }
    private static void DrawLine(object[] parameters, Graphics graphics)
    {
      string drawingID = (parameters[1] as string).Trim();
      if (nameSpaceTreeView.NodeIDs[drawingID].isChecked)
      {
        Vector2 start = (Vector2)parameters[2];
        Vector2 end = (Vector2)parameters[3];
        double lineWidth = (double)parameters[4];
        Color color = (Color)parameters[5];

        Pen pen = new Pen(color, (float)lineWidth);
        graphics.DrawLine(pen,
            (float)start.x, (float)start.y,
            (float)(end.x), (float)end.y);
      }
    }
    private static void DrawText(object[] parameters, Graphics graphics)
    {
      string drawingID = (parameters[1] as string).Trim();
      if (nameSpaceTreeView.NodeIDs[drawingID].isChecked)
      {
        string text = (string)parameters[2];
        Vector2 position = (Vector2)parameters[3];
        double size = (double)parameters[4];
        Color color = (Color)parameters[5];

        Font font = new Font("Arial", (float)size, FontStyle.Bold);
        SolidBrush brush = new SolidBrush(color);
        DrawingTools.DrawFlippedText(graphics, text, font, brush, (float)position.x, (float)position.y);
      }
    }

    public static void CreateDot(string id, Vector2 center, double size, Color color)
    {
      object[] parameters = new object[5];
      parameters[0] = "dot";
      parameters[1] = id;
      parameters[2] = center;
      parameters[3] = size;
      parameters[4] = color;
      CreateDrawing(id, parameters);
    }
    public static void CreateCircle(string id, Vector2 center, double radius, double lineWidth, Color color)
    {
      object[] parameters = new object[6];
      parameters[0] = "circle";
      parameters[1] = id;
      parameters[2] = center;
      parameters[3] = radius;
      parameters[4] = lineWidth;
      parameters[5] = color;
      CreateDrawing(id, parameters);
    }
    public static void CreateFilledCircle(string id, Vector2 center, double radius, Color color)
    {
      object[] parameters = new object[6];
      parameters[0] = "filledCircle";
      parameters[1] = id;
      parameters[2] = center;
      parameters[3] = radius;
      parameters[4] = color;
      CreateDrawing(id, parameters);
    }
    public static void CreateRectangle(string id, Vector2 bottomLeftCorner, Vector2 topRightCorner, double lineWidth, Color color)
    {
      object[] parameters = new object[6];
      parameters[0] = "rectangle";
      parameters[1] = id;
      parameters[2] = bottomLeftCorner;
      parameters[3] = topRightCorner;
      parameters[4] = lineWidth;
      parameters[5] = color;
      CreateDrawing(id, parameters);
    }
    public static void CreateLine(string id, Vector2 start, Vector2 end, double lineWidth, Color color)
    {
      object[] parameters = new object[6];
      parameters[0] = "line";
      parameters[1] = id;
      parameters[2] = start;
      parameters[3] = end;
      parameters[4] = lineWidth;
      parameters[5] = color;
      CreateDrawing(id, parameters);
    }
    public static void CreateArrow(string id, Vector2 start, Vector2 end, double lineWidth, Color color)
    {
      object[] parameters = new object[6];
      parameters[0] = "arrow";
      parameters[1] = id;
      parameters[2] = start;
      parameters[3] = end;
      parameters[4] = lineWidth;
      parameters[5] = color;
      CreateDrawing(id, parameters);
    }
    public static void CreateText(string id, string text, Vector2 position, double size, Color color)
    {
      object[] parameters = new object[6];
      parameters[0] = "text";
      parameters[1] = id;
      parameters[2] = text;
      parameters[3] = position;
      parameters[4] = size;
      parameters[5] = color;
      CreateDrawing(id, parameters);
    }
    #endregion
  }
}
